home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ADA Programming Guide
/
ADA Programming Guide.iso
/
ada_lrm
/
chap12.doc
< prev
next >
Wrap
Text File
|
1996-01-30
|
42KB
|
1,032 lines
12. Generic Units
A generic unit is a program unit that is either a generic subprogram or a
generic package. A generic unit is a template, which is parameterized or
not, and from which corresponding (nongeneric) subprograms or packages can
be obtained. The resulting program units are said to be instances of the
original generic unit.
A generic unit is declared by a generic declaration. This form of
declaration has a generic formal part declaring any generic formal
parameters. An instance of a generic unit is obtained as the result of a
generic instantiation with appropriate generic actual parameters for the
generic formal parameters. An instance of a generic subprogram is a
subprogram. An instance of a generic package is a package.
Generic units are templates. As templates they do not have the properties
that are specific to their nongeneric counterparts. For example, a generic
subprogram can be instantiated but it cannot be called. In contrast, the
instance of a generic subprogram is a nongeneric subprogram; hence, this
instance can be called but it cannot be used to produce further instances.
References: declaration 3.1, generic actual parameter 12.3, generic
declaration 12.1, generic formal parameter 12.1, generic formal part 12.1,
generic instantiation 12.3, generic package 12.1, generic subprogram 12.1,
instance 12.3, package 7, program unit 6, subprogram 6
12.1 Generic Declarations
A generic declaration declares a generic unit, which is either a generic
subprogram or a generic package. A generic declaration includes a generic
formal part declaring any generic formal parameters. A generic formal
parameter can be an object; alternatively (unlike a parameter of a
subprogram), it can be a type or a subprogram.
generic_declaration ::= generic_specification;
generic_specification ::=
generic_formal_part subprogram_specification
| generic_formal_part package_specification
generic_formal_part ::= generic {generic_parameter_declaration}
generic_parameter_declaration ::=
identifier_list : [in [out]] type_mark [:= expression];
| type identifier is generic_type_definition;
| private_type_declaration
| with subprogram_specification [is name];
| with subprogram_specification [is <>];
generic_type_definition ::=
(<>) | range <> | digits <> | delta <>
| array_type_definition | access_type_definition
The terms generic formal object (or simply, formal object), generic formal
type (or simply, formal type), and generic formal subprogram (or simply,
formal subprogram) are used to refer to corresponding generic formal
parameters.
The only form of subtype indication allowed within a generic formal part is
a type mark (that is, the subtype indication must not include an explicit
constraint). The designator of a generic subprogram must be an identifier.
Outside the specification and body of a generic unit, the name of this
program unit denotes the generic unit. In contrast, within the declarative
region associated with a generic subprogram, the name of this program unit
denotes the subprogram obtained by the current instantiation of the generic
unit. Similarly, within the declarative region associated with a generic
package, the name of this program unit denotes the package obtained by the
current instantiation.
The elaboration of a generic declaration has no other effect.
Examples of generic formal parts:
generic -- parameterless
generic
SIZE : NATURAL; -- formal object
generic
LENGTH : INTEGER := 200; -- formal object with a default expression
AREA : INTEGER := LENGTH*LENGTH; -- formal object with a default expression
generic
type ITEM is private; -- formal type
type INDEX is (<>); -- formal type
type ROW is array(INDEX range <>) of ITEM; -- formal type
with function "<"(X, Y : ITEM) return BOOLEAN; -- formal subprogram
Examples of generic declarations declaring generic subprograms:
generic
type ELEM is private;
procedure EXCHANGE(U, V : in out ELEM);
generic
type ITEM is private;
with function "*"(U, V : ITEM) return ITEM is <>;
function SQUARING(X : ITEM) return ITEM;
Example of a generic declaration declaring a generic package:
generic
type ITEM is private;
type VECTOR is array (POSITIVE range <>) of ITEM;
with function SUM(X, Y : ITEM) return ITEM;
package ON_VECTORS is
function SUM (A, B : VECTOR) return VECTOR;
function SIGMA(A : VECTOR) return ITEM;
LENGTH_ERROR : exception;
end;
Notes:
Within a generic subprogram, the name of this program unit acts as the name
of a subprogram. Hence this name can be overloaded, and it can appear in a
recursive call of the current instantiation. For the same reason, this
name cannot appear after the reserved word new in a (recursive) generic
instantiation.
An expression that occurs in a generic formal part is either the default
expression for a generic formal object of mode in, or a constituent of an
entry name given as default name for a formal subprogram, or the default
expression for a parameter of a formal subprogram. Default expressions for
generic formal objects and default names for formal subprograms are only
evaluated for generic instantiations that use such defaults. Default
expressions for parameters of formal subprograms are only evaluated for
calls of the formal subprograms that use such defaults. (The usual
visibility rules apply to any name used in a default expression: the
denoted entity must therefore be visible at the place of the expression.)
Neither generic formal parameters nor their attributes are allowed
constituents of static expressions (see 4.9).
References: access type definition 3.8, array type definition 3.6,
attribute 4.1.4, constraint 3.3, declaration 3.1, designator 6.1,
elaboration has no other effect 3.1, entity 3.1, expression 4.4, function
6.5, generic instantiation 12.3, identifier 2.3, identifier list 3.2,
instance 12.3, name 4.1, object 3.2, overloading 6.6 8.7, package
specification 7.1, parameter of a subprogram 6.2, private type definition
7.4, procedure 6.1, reserved word 2.9, static expression 4.9, subprogram 6,
subprogram specification 6.1, subtype indication 3.3.2, type 3.3, type mark
3.3.2
12.1.1 Generic Formal Objects
The first form of generic parameter declaration declares generic formal
objects. The type of a generic formal object is the base type of the type
denoted by the type mark given in the generic parameter declaration. A
generic parameter declaration with several identifiers is equivalent to a
sequence of single generic parameter declarations, as explained in section
3.2.
A generic formal object has a mode that is either in or in out. In the
absence of an explicit mode indication in a generic parameter declaration,
the mode in is assumed; otherwise the mode is the one indicated. If a
generic parameter declaration ends with an expression, the expression is
the default expression of the generic formal parameter. A default
expression is only allowed if the mode is in (whether this mode is
indicated explicitly or implicitly). The type of a default expression must
be that of the corresponding generic formal parameter.
A generic formal object of mode in is a constant whose value is a copy of
the value supplied as the matching generic actual parameter in a generic
instantiation, as described in section 12.3. The type of a generic formal
object of mode in must not be a limited type; the subtype of such a
generic formal object is the subtype denoted by the type mark given in the
generic parameter declaration.
A generic formal object of mode in out is a variable and denotes the object
supplied as the matching generic actual parameter in a generic
instantiation, as described in section 12.3. The constraints that apply to
the generic formal object are those of the corresponding generic actual
parameter.
Note:
The constraints that apply to a generic formal object of mode in out are
those of the corresponding generic actual parameter (not those implied by
the type mark that appears in the generic parameter declaration). Whenever
possible (to avoid confusion) it is recommended that the name of a base
type be used for the declaration of such a formal object. If, however, the
base type is anonymous, it is recommended that the subtype name defined by
the type declaration for the base type be used.
References: anonymous type 3.3.1, assignment 5.2, base type 3.3, constant
declaration 3.2, constraint 3.3, declaration 3.1, generic actual parameter
12.3, generic formal object 12.1, generic formal parameter 12.1, generic
instantiation 12.3, generic parameter declaration 12.1, identifier 2.3,
limited type 7.4.4, matching generic actual parameter 12.3, mode 6.1, name
4.1, object 3.2, simple name 4.1, subtype 3.3, type declaration 3.3, type
mark 3.3.2, variable 3.2.1
12.1.2 Generic Formal Types
A generic parameter declaration that includes a generic type definition or
a private type declaration declares a generic formal type. A generic
formal type denotes the subtype supplied as the corresponding actual
parameter in a generic instantiation, as described in 12.3(d). However,
within a generic unit, a generic formal type is considered as being
distinct from all other (formal or nonformal) types. The form of
constraint applicable to a formal type in a subtype indication depends on
the class of the type as for a nonformal type.
The only form of discrete range that is allowed within the declaration of a
generic formal (constrained) array type is a type mark.
The discriminant part of a generic formal private type must not include a
default expression for a discriminant. (Consequently, a variable that is
declared by an object declaration must be constrained if its type is a
generic formal type with discriminants.)
Within the declaration and body of a generic unit, the operations available
for values of a generic formal type (apart from any additional operation
specified by a generic formal subprogram) are determined by the generic
parameter declaration for the formal type:
(a) For a private type declaration, the available operations are those
defined in section 7.4.2 (in particular, assignment, equality, and
inequality are available for a private type unless it is limited).
(b) For an array type definition, the available operations are those
defined in section 3.6.2 (for example, they include the formation of
indexed components and slices).
(c) For an access type definition, the available operations are those
defined in section 3.8.2 (for example, allocators can be used).
The four forms of generic type definition in which a box appears (that is,
the compound delimiter <>) correspond to the following major forms of
scalar type:
(d) Discrete types: (<>)
The available operations are the operations common to enumeration and
integer types; these are defined in section 3.5.5.
(e) Integer types: range <>
The available operations are the operations of integer types defined
in section 3.5.5.
(f) Floating point types: digits <>
The available operations are those defined in section 3.5.8.
(g) Fixed point types: delta <>
The available operations are those defined in section 3.5.10.
In all of the above cases (a) through (f), each operation implicitly
associated with a formal type (that is, other than an operation specified
by a formal subprogram) is implicitly declared at the place of the
declaration of the formal type. The same holds for a formal fixed point
type, except for the multiplying operators that deliver a result of the
type universal_fixed (see 4.5.5), since these special operators are
declared in the package STANDARD.
For an instantiation of the generic unit, each of these operations is the
corresponding basic operation or predefined operator of the matching actual
type. For an operator, this rule applies even if the operator has been
redefined for the actual type or for some parent type of the actual type.
Examples of generic formal types:
type ITEM is private;
type BUFFER(LENGTH : NATURAL) is limited private;
type ENUM is (<>);
type INT is range <>;
type ANGLE is delta <>;
type MASS is digits <>;
type TABLE is array (ENUM) of ITEM;
Example of a generic formal part declaring a formal integer type:
generic
type RANK is range <>;
FIRST : RANK := RANK'FIRST;
SECOND : RANK := FIRST + 1; -- the operator "+" of the type RANK
References: access type definition 3.8, allocator 4.8, array type
definition 3.6, assignment 5.2, body of a generic unit 12.2, class of type
3.3, constraint 3.3, declaration 3.1, declaration of a generic unit 12.1,
discrete range 3.6, discrete type 3.5, discriminant part 3.7.1, enumeration
type 3.5.1, equality 4.5.2, fixed point type 3.5.9, floating point type
3.5.7, generic actual type 12.3, generic formal part 12.1, generic formal
subprogram 12.1.3, generic formal type 12.1, generic parameter declaration
12.1, generic type definition 12.1, indexed component 4.1.1, inequality
4.5.2, instantiation 12.3, integer type 3.5.4, limited private type 7.4.4,
matching generic actual type 12.3.2 12.3.3 12.3.4 12.3.5, multiplying
operator 4.5 4.5.5, operation 3.3, operator 4.5, parent type 3.4, private
type definition 7.4, scalar type 3.5, slice 4.1.2, standard package 8.6 C,
subtype indication 3.3.2, type mark 3.3.2, universal_fixed 3.5.9
12.1.3 Generic Formal Subprograms
A generic parameter declaration that includes a subprogram specification
declares a generic formal subprogram.
Two alternative forms of defaults can be specified in the declaration of a
generic formal subprogram. In these forms, the subprogram specification is
followed by the reserved word is and either a box or the name of a
subprogram or entry. The matching rules for these defaults are explained
in section 12.3.6.
A generic formal subprogram denotes the subprogram, enumeration literal, or
entry supplied as the corresponding generic actual parameter in a generic
instantiation, as described in section 12.3(f).
Examples of generic formal subprograms:
with function INCREASE(X : INTEGER) return INTEGER;
with function SUM(X, Y : ITEM) return ITEM;
with function "+"(X, Y : ITEM) return ITEM is <>;
with function IMAGE(X : ENUM) return STRING is ENUM'IMAGE;
with procedure UPDATE is DEFAULT_UPDATE;
Notes:
The constraints that apply to a parameter of a formal subprogram are those
of the corresponding parameter in the specification of the matching actual
subprogram (not those implied by the corresponding type mark in the
specification of the formal subprogram). A similar remark applies to the
result of a function. Whenever possible (to avoid confusion), it is
recommended that the name of a base type be used rather than the name of a
subtype in any declaration of a formal subprogram. If, however, the base
type is anonymous, it is recommended that the subtype name defined by the
type declaration be used.
The type specified for a formal parameter of a generic formal subprogram
can be any visible type, including a generic formal type of the same
generic formal part.
References: anonymous type 3.3.1, base type 3.3, box delimiter 12.1.2,
constraint 3.3, designator 6.1, generic actual parameter 12.3, generic
formal function 12.1, generic formal subprogram 12.1, generic instantiation
12.3, generic parameter declaration 12.1, identifier 2.3, matching generic
actual subprogram 12.3.6, operator symbol 6.1, parameter of a subprogram
6.2, renaming declaration 8.5, reserved word 2.9, scope 8.2, subprogram 6,
subprogram specification 6.1, subtype 3.3.2, type 3.3, type mark 3.3.2
12.2 Generic Bodies
The body of a generic subprogram or generic package is a template for the
bodies of the corresponding subprograms or packages obtained by generic
instantiations. The syntax of a generic body is identical to that of a
nongeneric body.
For each declaration of a generic subprogram, there must be a corresponding
body.
The elaboration of a generic body has no other effect than to establish
that the body can from then on be used as the template for obtaining the
corresponding instances.
Example of a generic procedure body:
procedure EXCHANGE(U, V : in out ELEM) is -- see example in 12.1
T : ELEM; -- the generic formal type
begin
T := U;
U := V;
V := T;
end EXCHANGE;
Example of a generic function body:
function SQUARING(X : ITEM) return ITEM is -- see example in 12.1
begin
return X*X; -- the formal operator "*"
end;
Example of a generic package body:
package body ON_VECTORS is -- see example in 12.1
function SUM(A, B : VECTOR) return VECTOR is
RESULT : VECTOR(A'RANGE); -- the formal type VECTOR
BIAS : constant INTEGER := B'FIRST - A'FIRST;
begin
if A'LENGTH /= B'LENGTH then
raise LENGTH_ERROR;
end if;
for N in A'RANGE loop
RESULT(N) := SUM(A(N), B(N + BIAS)); -- the formal function SUM
end loop;
return RESULT;
end;
function SIGMA(A : VECTOR) return ITEM is
TOTAL : ITEM := A(A'FIRST); -- the formal type ITEM
begin
for N in A'FIRST + 1 .. A'LAST loop
TOTAL := SUM(TOTAL, A(N)); -- the formal function SUM
end loop;
return TOTAL;
end;
end;
References: body 3.9, elaboration 3.9, generic body 12.1, generic
instantiation 12.3, generic package 12.1, generic subprogram 12.1, instance
12.3, package body 7.1, package 7, subprogram 6, subprogram body 6.3
12.3 Generic Instantiation
An instance of a generic unit is declared by a generic instantiation.
generic_instantiation ::=
package identifier is
new generic_package_name [generic_actual_part];
| procedure identifier is
new generic_procedure_name [generic_actual_part];
| function designator is
new generic_function_name [generic_actual_part];
generic_actual_part ::=
(generic_association {, generic_association})
generic_association ::=
[generic_formal_parameter =>] generic_actual_parameter
generic_formal_parameter ::= parameter_simple_name | operator_symbol
generic_actual_parameter ::= expression | variable_name
| subprogram_name | entry_name | type_mark
An explicit generic actual parameter must be supplied for each generic
formal parameter, unless the corresponding generic parameter declaration
specifies that a default can be used. Generic associations can be either
positional or named in the same manner as parameter associations of
subprogram calls (see 6.4). If two or more formal subprograms have the
same designator, then named associations are not allowed for the
corresponding generic parameters.
Each generic actual parameter must match the corresponding generic formal
parameter. An expression can match a formal object of mode in; a variable
name can match a formal object of mode in out; a subprogram name or an
entry name can match a formal subprogram; a type mark can match a formal
type. The detailed rules defining the allowed matches are given in
sections 12.3.1 to 12.3.6; these are the only allowed matches.
The instance is a copy of the generic unit, apart from the generic formal
part; thus the instance of a generic package is a package, that of a
generic procedure is a procedure, and that of a generic function is a
function. For each occurrence, within the generic unit, of a name that
denotes a given entity, the following list defines which entity is denoted
by the corresponding occurrence within the instance.
(a) For a name that denotes the generic unit: The corresponding
occurrence denotes the instance.
(b) For a name that denotes a generic formal object of mode in: The
corresponding name denotes a constant whose value is a copy of the
value of the associated generic actual parameter.
(c) For a name that denotes a generic formal object of mode in out: The
corresponding name denotes the variable named by the associated
generic actual parameter.
(d) For a name that denotes a generic formal type: The corresponding
name denotes the subtype named by the associated generic actual
parameter (the actual subtype).
(e) For a name that denotes a discriminant of a generic formal type: The
corresponding name denotes the corresponding discriminant (there must
be one) of the actual type associated with the generic formal type.
(f) For a name that denotes a generic formal subprogram: The
corresponding name denotes the subprogram, enumeration literal, or
entry named by the associated generic actual parameter (the actual
subprogram).
(g) For a name that denotes a formal parameter of a generic formal
subprogram: The corresponding name denotes the corresponding formal
parameter of the actual subprogram associated with the formal
subprogram.
(h) For a name that denotes a local entity declared within the generic
unit: The corresponding name denotes the entity declared by the
corresponding local declaration within the instance.
(i) For a name that denotes a global entity declared outside of the
generic unit: The corresponding name denotes the same global entity.
Similar rules apply to operators and basic operations: in particular,
formal operators follow a rule similar to rule (f), local operations follow
a rule similar to rule (h), and operations for global types follow a rule
similar to rule (i). In addition, if within the generic unit a predefined
operator or basic operation of a formal type is used, then within the
instance the corresponding occurrence refers to the corresponding
predefined operation of the actual type associated with the formal type.
The above rules apply also to any type mark or (default) expression given
within the generic formal part of the generic unit.
For the elaboration of a generic instantiation, each expression supplied as
an explicit generic actual parameter is first evaluated, as well as each
expression that appears as a constituent of a variable name or entry name
supplied as an explicit generic actual parameter; these evaluations
proceed in some order that is not defined by the language. Then, for each
omitted generic association (if any), the corresponding default expression
or default name is evaluated; such evaluations are performed in the order
of the generic parameter declarations. Finally, the implicitly generated
instance is elaborated. The elaboration of a generic instantiation may
also involve certain constraint checks as described in later subsections.
Recursive generic instantiation is not allowed in the following sense: if
a given generic unit includes an instantiation of a second generic unit,
then the instance generated by this instantiation must not include an
instance of the first generic unit (whether this instance is generated
directly, or indirectly by intermediate instantiations).
Examples of generic instantiations (see 12.1):
procedure SWAP is new EXCHANGE(ELEM => INTEGER);
procedure SWAP is new EXCHANGE(CHARACTER); -- SWAP is overloaded
function SQUARE is new SQUARING(INTEGER); -- "*" of INTEGER used by default
function SQUARE is new SQUARING(ITEM => MATRIX, "*" => MATRIX_PRODUCT);
function SQUARE is new SQUARING(MATRIX, MATRIX_PRODUCT); -- same as previous
package INT_VECTORS is new ON_VECTORS(INTEGER, TABLE, "+");
Examples of uses of instantiated units:
SWAP(A, B);
A := SQUARE(A);
T : TABLE(1 .. 5) := (10, 20, 30, 40, 50);
N : INTEGER := INT_VECTORS.SIGMA(T); -- 150 (see 12.2 for the body of SIGMA)
use INT_VECTORS;
M : INTEGER := SIGMA(T); -- 150
Notes:
Omission of a generic actual parameter is only allowed if a corresponding
default exists. If default expressions or default names (other than simple
names) are used, they are evaluated in the order in which the corresponding
generic formal parameters are declared.
If two overloaded subprograms declared in a generic package specification
differ only by the (formal) type of their parameters and results, then
there exist legal instantiations for which all calls of these subprograms
from outside the instance are ambiguous. For example:
generic
type A is (<>);
type B is private;
package G is
function NEXT(X : A) return A;
function NEXT(X : B) return B;
end;
package P is new G(A => BOOLEAN, B => BOOLEAN);
-- calls of P.NEXT are ambiguous
References: declaration 3.1, designator 6.1, discriminant 3.7.1,
elaboration 3.1 3.9, entity 3.1, entry name 9.5, evaluation 4.5, expression
4.4, generic formal object 12.1, generic formal parameter 12.1, generic
formal subprogram 12.1, generic formal type 12.1, generic parameter
declaration 12.1, global declaration 8.1, identifier 2.3, implicit
declaration 3.1, local declaration 8.1, mode in 12.1.1, mode in out 12.1.1,
name 4.1, operation 3.3, operator symbol 6.1, overloading 6.6 8.7, package
7, simple name 4.1, subprogram 6, subprogram call 6.4, subprogram name 6.1,
subtype declaration 3.3.2, type mark 3.3.2, variable 3.2.1, visibility 8.3
12.3.1 Matching Rules for Formal Objects
A generic formal parameter of mode in of a given type is matched by an
expression of the same type. If a generic unit has a generic formal object
of mode in, a check is made that the value of the expression belongs to
the subtype denoted by the type mark, as for an explicit constant
declaration (see 3.2.1). The exception CONSTRAINT_ERROR is raised if this
check fails.
A generic formal parameter of mode in out of a given type is matched by the
name of a variable of the same type. The variable must not be a formal
parameter of mode out or a subcomponent thereof. The name must denote a
variable for which renaming is allowed (see 8.5).
Notes:
The type of a generic actual parameter of mode in must not be a limited
type. The constraints that apply to a generic formal parameter of mode in
out are those of the corresponding generic actual parameter (see 12.1.1).
References: constraint 3.3, constraint_error exception 11.1, expression
4.4, formal parameter 6.1, generic actual parameter 12.3, generic formal
object 12.1.1, generic formal parameter 12.1, generic instantiation 12.3,
generic unit 12.1, limited type 7.4.4, matching generic actual parameter
12.3, mode in 12.1.1, mode in out 12.1.1, mode out 6.2, name 4.1, raising
of exceptions 11, satisfy 3.3, subcomponent 3.3, type 3.3, type mark 3.3.2,
variable 3.2.1
12.3.2 Matching Rules for Formal Private Types
A generic formal private type is matched by any type or subtype (the actual
subtype) that satisfies the following conditions:
- If the formal type is not limited, the actual type must not be a
limited type. (If, on the other hand, the formal type is limited, no
such condition is imposed on the corresponding actual type, which can
be limited or not limited.)
- If the formal type has a discriminant part, the actual type must be a
type with the same number of discriminants; the type of a
discriminant that appears at a given position in the discriminant part
of the actual type must be the same as the type of the discriminant
that appears at the same position in the discriminant part of the
formal type; and the actual subtype must be unconstrained. (If, on
the other hand, the formal type has no discriminants, the actual type
is allowed to have discriminants.)
Furthermore, consider any occurrence of the name of the formal type at a
place where this name is used as an unconstrained subtype indication. The
actual subtype must not be an unconstrained array type or an unconstrained
type with discriminants, if any of these occurrences is at a place where
either a constraint or default discriminants would be required for an array
type or for a type with discriminants (see 3.6.1 and 3.7.2). The same
restriction applies to occurrences of the name of a subtype of the formal
type, and to occurrences of the name of any type or subtype derived,
directly or indirectly, from the formal type.
If a generic unit has a formal private type with discriminants, the
elaboration of a corresponding generic instantiation checks that the
subtype of each discriminant of the actual type is the same as the subtype
of the corresponding discriminant of the formal type. The exception
CONSTRAINT_ERROR is raised if this check fails.
References: array type 3.6, constraint 3.3, constraint_error exception
11.1, default expression for a discriminant 3.7.1, derived type 3.4,
discriminant 3.7.1, discriminant part 3.7.1, elaboration 3.9, generic
actual type 12.3, generic body 12.2, generic formal type 12.1.2, generic
instantiation 12.3, generic specification 12.1, limited type 7.4.4,
matching generic actual parameter 12.3, name 4.1, private type 7.4, raising
of exceptions 11, subtype 3.3, subtype indication 3.3.2, type 3.3, type
with discriminants 3.3, unconstrained array type 3.6, unconstrained subtype
3.3
12.3.3 Matching Rules for Formal Scalar Types
A generic formal type defined by (<>) is matched by any discrete subtype
(that is, any enumeration or integer subtype). A generic formal type
defined by range <> is matched by any integer subtype. A generic formal
type defined by digits <> is matched by any floating point subtype. A
generic formal type defined by delta <> is matched by any fixed point
subtype. No other matches are possible for these generic formal types.
References: box delimiter 12.1.2, discrete type 3.5, enumeration type
3.5.1, fixed point type 3.5.9, floating point type 3.5.7, generic actual
type 12.3, generic formal type 12.1.2, generic type definition 12.1,
integer type 3.5.4, matching generic actual parameter 12.3, scalar type 3.5
12.3.4 Matching Rules for Formal Array Types
A formal array type is matched by an actual array subtype that satisfies
the following conditions:
- The formal array type and the actual array type must have the same
dimensionality; the formal type and the actual subtype must be either
both constrained or both unconstrained.
- For each index position, the index type must be the same for the
actual array type as for the formal array type.
- The component type must be the same for the actual array type as for
the formal array type. If the component type is other than a scalar
type, then the component subtypes must be either both constrained or
both unconstrained.
If a generic unit has a formal array type, the elaboration of a
corresponding instantiation checks that the constraints (if any) on the
component type are the same for the actual array type as for the formal
array type, and likewise that for any given index position the index
subtypes or the discrete ranges have the same bounds. The exception
CONSTRAINT_ERROR is raised if this check fails.
Example:
-- given the generic package
generic
type ITEM is private;
type INDEX is (<>);
type VECTOR is array (INDEX range <>) of ITEM;
type TABLE is array (INDEX) of ITEM;
package P is
...
end;
-- and the types
type MIX is array (COLOR range <>) of BOOLEAN;
type OPTION is array (COLOR) of BOOLEAN;
-- then MIX can match VECTOR and OPTION can match TABLE
package R is new P(ITEM => BOOLEAN, INDEX => COLOR,
VECTOR => MIX, TABLE => OPTION);
-- Note that MIX cannot match TABLE and OPTION cannot match VECTOR
Note:
For the above rules, if any of the index or component types of the formal
array type is itself a formal type, then within the instance its name
denotes the corresponding actual subtype (see 12.3(d)).
References: array type 3.6, array type definition 3.6, component of an
array 3.6, constrained array type 3.6, constraint 3.3, constraint_error
exception 11.1, elaboration 3.9, formal type 12.1, generic formal type
12.1.2, generic instantiation 12.3, index 3.6, index constraint 3.6.1,
matching generic actual parameter 12.3, raise statement 11.3, subtype 3.3,
unconstrained array type 3.6
12.3.5 Matching Rules for Formal Access Types
A formal access type is matched by an actual access subtype if the type of
the designated objects is the same for the actual type as for the formal
type. If the designated type is other than a scalar type, then the
designated subtypes must be either both constrained or both unconstrained.
If a generic unit has a formal access type, the elaboration of a
corresponding instantiation checks that any constraints on the designated
objects are the same for the actual access subtype as for the formal access
type. The exception CONSTRAINT_ERROR is raised if this check fails.
Example:
-- the formal types of the generic package
generic
type NODE is private;
type LINK is access NODE;
package P is
...
end;
-- can be matched by the actual types
type CAR;
type CAR_NAME is access CAR;
type CAR is
record
PRED, SUCC : CAR_NAME;
NUMBER : LICENSE_NUMBER;
OWNER : PERSON;
end record;
-- in the following generic instantiation
package R is new P(NODE => CAR, LINK => CAR_NAME);
Note:
For the above rules, if the designated type is itself a formal type, then
within the instance its name denotes the corresponding actual subtype (see
12.3(d)).
References: access type 3.8, access type definition 3.8, constraint 3.3,
constraint_error exception 11.1, designate 3.8, elaboration 3.9, generic
formal type 12.1.2, generic instantiation 12.3, matching generic actual
parameter 12.3, object 3.2, raise statement 11.3, value of access type 3.8
12.3.6 Matching Rules for Formal Subprograms
A formal subprogram is matched by an actual subprogram, enumeration
literal, or entry if both have the same parameter and result type profile
(see 6.6); in addition, parameter modes must be identical for formal
parameters that are at the same parameter position.
If a generic unit has a default subprogram specified by a name, this name
must denote a subprogram, an enumeration literal, or an entry, that matches
the formal subprogram (in the above sense). The evaluation of the default
name takes place during the elaboration of each instantiation that uses the
default, as defined in section 12.3.
If a generic unit has a default subprogram specified by a box, the
corresponding actual parameter can be omitted if a subprogram, enumeration
literal, or entry matching the formal subprogram, and with the same
designator as the formal subprogram, is directly visible at the place of
the generic instantiation; this subprogram, enumeration literal, or entry
is then used by default (there must be exactly one subprogram, enumeration
literal, or entry satisfying the previous conditions).
Example:
-- given the generic function specification
generic
type ITEM is private;
with function "*" (U, V : ITEM) return ITEM is <>;
function SQUARING(X : ITEM) return ITEM;
-- and the function
function MATRIX_PRODUCT(A, B : MATRIX) return MATRIX;
-- the following instantiation is possible
function SQUARE is new SQUARING(MATRIX, MATRIX_PRODUCT);
-- the following instantiations are equivalent
function SQUARE is new SQUARING(ITEM => INTEGER, "*" => "*");
function SQUARE is new SQUARING(INTEGER, "*");
function SQUARE is new SQUARING(INTEGER);
Notes:
The matching rules for formal subprograms state requirements that are
similar to those applying to subprogram renaming declarations (see 8.5).
In particular, the name of a parameter of the formal subprogram need not be
the same as that of the corresponding parameter of the actual subprogram;
similarly, for these parameters, default expressions need not correspond.
A formal subprogram is matched by an attribute of a type if the attribute
is a function with a matching specification. An enumeration literal of a
given type matches a parameterless formal function whose result type is the
given type.
References: attribute 4.1.4, box delimiter 12.1.2, designator 6.1, entry
9.5, function 6.5, generic actual type 12.3, generic formal subprogram
12.1.3, generic formal type 12.1.2, generic instantiation 12.3, matching
generic actual parameter 12.3, name 4.1, parameter and result type profile
6.3, subprogram 6, subprogram specification 6.1, subtype 3.3, visibility
8.3
12.4 Example of a Generic Package
The following example provides a possible formulation of stacks by means of
a generic package. The size of each stack and the type of the stack
elements are provided as generic parameters.
generic
SIZE : POSITIVE;
type ITEM is private;
package STACK is
procedure PUSH(E : in ITEM);
procedure POP (E : out ITEM);
OVERFLOW, UNDERFLOW : exception;
end STACK;
package body STACK is
type TABLE is array (POSITIVE range <>) of ITEM;
SPACE : TABLE(1 .. SIZE);
INDEX : NATURAL := 0;
procedure PUSH(E : in ITEM) is
begin
if INDEX >= SIZE then
raise OVERFLOW;
end if;
INDEX := INDEX + 1;
SPACE(INDEX) := E;
end PUSH;
procedure POP(E : out ITEM) is
begin
if INDEX = 0 then
raise UNDERFLOW;
end if;
E := SPACE(INDEX);
INDEX := INDEX - 1;
end POP;
end STACK;
Instances of this generic package can be obtained as follows:
package STACK_INT is new STACK(SIZE => 200, ITEM => INTEGER);
package STACK_BOOL is new STACK(100, BOOLEAN);
Thereafter, the procedures of the instantiated packages can be called as
follows:
STACK_INT.PUSH(N);
STACK_BOOL.PUSH(TRUE);
Alternatively, a generic formulation of the type STACK can be given as
follows (package body omitted):
generic
type ITEM is private;
package ON_STACKS is
type STACK(SIZE : POSITIVE) is limited private;
procedure PUSH(S : in out STACK; E : in ITEM);
procedure POP (S : in out STACK; E : out ITEM);
OVERFLOW, UNDERFLOW : exception;
private
type TABLE is array (POSITIVE range <>) of ITEM;
type STACK(SIZE : POSITIVE) is
record
SPACE : TABLE(1 .. SIZE);
INDEX : NATURAL := 0;
end record;
end;
In order to use such a package, an instantiation must be created and
thereafter stacks of the corresponding type can be declared:
declare
package STACK_REAL is new ON_STACKS(REAL); use STACK_REAL;
S : STACK(100);
begin
...
PUSH(S, 2.54);
...
end;